/* Copyright 2001,2002,2003 NAH6 BV
 * All Rights Reserved
 *
 *  $Header: /var/lib/cvs/secphone/ui/phone/PhoneHandler.h,v 1.7 2003/11/21 12:39:24 itsme Exp $
 *
 *
 */


#ifndef __PHONEHANDLER_H__

#include "nhthread.h"
#include "CallProgressSignalling.h"

// 'SP' = spipc events
// 'UI' = user interface events
// 'RCV'= autoanswer udc messages
// 'KX' = key exchange events

enum {
    EV_SP_RINGON=0,
    EV_SP_RINGOFF,
    EV_UI_USERREQUEST,
    EV_UI_USERSTOP,
    EV_UI_MUTE_ON,
    EV_UI_MUTE_OFF,
    EV_SP_CONNECT,
    EV_SP_DISCONNECT,       // in spipc language this is 2 messages: hangup + disconnect
    EV_SP_DIALSTART,
    EV_SP_ANSWERSTART,
    EV_RCV_AUTOANSWER_WAIT,
    EV_RCV_AUTOANSWER_CONNECT,
    EV_KX_DONE,
    EV_KX_FAILED,
    EV_TIMER,
    PHONE_NR_OF_EVENTS,
};

class CCPhoneDlg;

class PhoneHandler : public NHThread {
public:
    PhoneHandler(CCPhoneDlg& dlg);
    virtual ~PhoneHandler();

    enum TDisconnectReason {
        SP_DISCONNECT_NONE,
        SP_DISCONNECT_LOCAL_HANGUP,
        SP_DISCONNECT_NO_ANSWER,
        SP_DISCONNECT_REMOTE_ABORT,
        SP_DISCONNECT_REMOTE_BUSY,
        SP_DISCONNECT_REMOTE_HANGUP,
        SP_DISCONNECT_UNKNOWN,
        SP_DISCONNECT_UNREACHABLE
    };

    // misc functions
    TDisconnectReason FindDisconnectReason(BYTE reason, int result);
    CallProgressSignalling::TCallProgressTone GetToneForReason(TDisconnectReason reason);
    char *GetNameForReason(TDisconnectReason reason);

    // signals from external events
    void SignalPhoneAnswerStart();
    void SignalPhoneDialStart();
    void SignalPhoneRingOn();
    void SignalPhoneRingOff();
    void SignalUserRequest();
    void SignalUserAnswer();
    void SignalUserStop();
    bool SignalUserMuteOn();
    bool SignalUserMuteOff();
    void SignalPhoneConnect();
    void SignalPhoneDisconnect(TDisconnectReason reason);
    void SignalPhoneRemoteHangup();
    void SignalRcvAutoAnswerWait();
    void SignalRcvAutoAnswerConnect();
    void SignalKeyExchangeDone();
    void SignalKeyExchangeFailure();

    virtual void StartThread();

    void EnableTimer();
    void DisableTimer();
    static void CALLBACK staticTimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime);
    void TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime);

    void DoHangup();

protected:
    virtual DWORD ThreadProc();
    virtual const char* name() const { return "PhoneHandler"; }

public:
    void mainloop();

private:
        HANDLE              m_hEvents[PHONE_NR_OF_EVENTS];
        DWORD               m_dwCurrentWait;

        bool                m_call_answered;
        TDisconnectReason   m_disconnect_reason;

        CCPhoneDlg&         m_dlg;

		/////Frank 2008-07-10/////
		/*bool    firstFlag;*/
		//////////
    int WaitState(DWORD eventMask);

    void HandleOutgoingCall();
    void HandleIncomingCall();

    // outgoing call states
    bool WaitForDialStart();
    bool WaitForOutgoingConnect();
    bool WaitForOutgoingKeyExchange();
    bool WaitForRemoteAnswer();

    // incoming call states
    bool WaitForManualAnswerUserInput();
    bool WaitForIncomingConnect();
    bool WaitForAutoAnswerUserInput();
    bool WaitForIncomingKeyExchange();
    bool WaitForHangup();

    void Reset();

};

#define __PHONEHANDLER_H__
#endif
